Skip to content

Open Graph card + contrast/a11y pass - #8

Merged
dommango merged 2 commits into
mainfrom
feat/social-preview-and-a11y-pass
Sep 1, 2026
Merged

Open Graph card + contrast/a11y pass#8
dommango merged 2 commits into
mainfrom
feat/social-preview-and-a11y-pass

Conversation

@dommango

@dommango dommango commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Summary

Executes Plan 04 and Plan 08 from the 2026-08-31 site audit.

Plan 04 — Open Graph card, touch icon, theme color

  • scripts/render-og.mjs renders public/og.png (1200×630, brand tokens) and public/apple-touch-icon.png from a self-contained HTML template via Playwright — committed once, not built on every deploy.
  • app/layout.tsx: og:image/twitter:card=summary_large_image/apple-touch-icon/theme-color metadata.

Plan 08 — Contrast, focus, motion, mobile nav

  • New --accent-text/--btn-fg tokens so small accent-on-dark text and button/selection text clear WCAG AA 4.5:1 in all three themes (Gold/Oxblood/High Contrast) — __tests__/contrast.test.ts + lib/format/contrast.ts assert the measured pairs.
  • Visible :focus-visible ring in every theme, including High Contrast (previously white-on-white, invisible to keyboard users).
  • prefers-reduced-motion support: pulse/hover-lift animations are suppressed (verified !important, since the base hover rules share specificity with the media-query override).
  • Decorative L E T ' S T A L K text is aria-hidden; nav gets aria-label="Main" and a skip link to #projects.
  • Mobile nav (≤900px) gets a trailing-edge fade + arrow when more links are off-screen, clearing on scroll-to-end or keyboard focus (a masked/faded element would otherwise clip a tabbed-to link's focus ring).

A code-reviewer pass on Plan 08 caught two CRITICAL and several HIGH/MEDIUM issues before this was pushed — all fixed and re-verified:

  • Reduced-motion transform: none was losing a specificity tie to the base hover rules (no visible effect without !important).
  • The mobile nav's mask-image clipped the focus outline of a link inside the fade zone; :focus-within now lifts the mask.
  • .btn-primary:hover background in Oxblood dropped to 4.07:1 (below AA) — hover no longer lightens the fill.
  • Three selectors (.scrub-chip, .nf-count, .nf-stay:focus-visible) had been missed in the original accent→accent-text sweep.
  • ::selection was still 2.21:1 in the default Gold theme.
  • The scroll-affordance listener now also re-measures on resize and font-load, not just on scroll.
  • Skip link target (#projects) is focusable (tabIndex={-1}) so Safari actually moves focus there.

Test plan

  • npm test -- --run — 44/44 passing (incl. 6 new contrast-ratio tests)
  • npx tsc --noEmit — clean
  • npm run lint — clean (2 pre-existing warnings/errors in untouched files)
  • npm run build — OG/twitter/theme-color meta tags confirmed present in out/index.html
  • npx playwright test — 27/27 passing (horizontal-overflow and mobile-nav-reachable guards included)
  • Manual Playwright verification: mobile nav fade/arrow appears and clears correctly; skip link becomes visible on focus; reduced-motion actually suppresses card/button hover lift (not just the pulse); focus ring renders visibly in all three themes including a tabbed-to mobile nav link inside the fade zone; Oxblood button hover now measures white-on-#c8102e (5.88:1) instead of white-on-#e63d52 (4.07:1)

🤖 Generated with Claude Code

https://claude.ai/code/session_01TUH1L7Q2FfGYa8dS7Lqvtz

…on, mobile nav affordance

Adds --accent-text/--btn-fg tokens so accent-on-dark small text and
button/selection text clear WCAG AA in all three themes, restores a
visible focus ring in High Contrast (previously white-on-white), honors
prefers-reduced-motion, hides the decorative "L E T'S TALK" line from
screen readers, adds a skip link, and gives the mobile nav a fade+arrow
affordance that clears on scroll or keyboard focus.
@dommango
dommango merged commit 9f79453 into main Sep 1, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant